home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
IRIX 6.2 Applications 1996 May
/
SGI IRIX 6.2 Applications 1996 May.iso
/
dist
/
impr_dev.idb
/
usr
/
impressario
/
src
/
libstiff
/
printstiff.c.z
/
printstiff.c
Wrap
C/C++ Source or Header
|
1996-05-06
|
15KB
|
521 lines
/**************************************************************************
*
* Copyright (c) 1992 Silicon Graphics, Inc.
* All Rights Reserved
*
* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SGI
*
* The copyright notice above does not evidence any actual of intended
* publication of such source code, and is an unpublished work by Silicon
* Graphics, Inc. This material contains CONFIDENTIAL INFORMATION that is
* the property of Silicon Graphics, Inc. Any use, duplication or
* disclosure not specifically authorized by Silicon Graphics is strictly
* prohibited.
*
* RESTRICTED RIGHTS LEGEND:
*
* Use, duplication or disclosure by the Government is subject to
* restrictions as set forth in subdivision (c)(1)(ii) of the Rights in
* Technical Data and Computer Software clause at DFARS 52.227-7013,
* and/or in similar or successor clauses in the FAR, DOD or NASA FAR
* Supplement. Unpublished - rights reserved under the Copyright Laws of
* the United States. Contractor is SILICON GRAPHICS, INC., 2011 N.
* Shoreline Blvd., Mountain View, CA 94039-7311
**************************************************************************
*
* File: printstiff.c
*
* Description: Support for the printing STIFF API. This API is built
* on the base STIFF API. Functions in this API (PST) can be
* freely mixed with functions in the base STIFF API (ST).
*
* The PST functions simply write IFD's with more tags. These tags
* specify information relevant to image files destined for
* printers.
*
**************************************************************************/
#ident "$Revision: 1.8 $"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <bstring.h>
#include "printstiff.h"
#include "stiffp.h"
/* Private data block structure */
typedef struct {
PSTPrivateData *items;
unsigned long amount;
} PRIVATE_DATA;
/* Local functions */
static int add_private_data(PRIVATE_DATA*, unsigned short, STTagType,
unsigned long, void*);
static int get_private_data(PRIVATE_DATA*, unsigned short, STTagType*,
unsigned long*, void**);
static void free_private_data(PRIVATE_DATA*);
static int create_private_tag(STStream*, PRIVATE_DATA*);
/**************************************************************************
*
* Function: PSTWriteImageHeader
*
* Description: Writes a Print STIFF image file header. This is a STIFF
* IFD with additional tags.
*
* Parameters:
* st (I) - STIFF stream pointer
* pst_hdp (I) - pointer to a filled in Print STIFF header structure
* last (I) - 1 = last IFD to write, 0 = still more IFDs to come
*
* Return: 0 if successful and -1 if error.
*
**************************************************************************/
#define ADD_TAG(tag, type, len, datap) \
if (STAddTag(st, tag, type, len, (void*)(datap)) < 0) { \
return -1; \
}
#define ADD_PDATA(id, type, len, datap) \
if (add_private_data(&write_pblock, id, type, len, (void*)(datap)) < 0) { \
return -1; \
}
int PSTWriteImageHeader(STStream *st, PSTImageHeader *pst_hdp, int last)
{
STImageHeader st_hd;
int status;
unsigned long res[2];
unsigned long subfile = 0;
static PRIVATE_DATA write_pblock;
/*
* Set up an ST header
*/
st_hd.width = pst_hdp->width;
st_hd.height = pst_hdp->height;
st_hd.bitsPerSample = pst_hdp->bitsPerSample;
st_hd.samplesPerPixel = pst_hdp->samplesPerPixel;
st_hd.imgbytes = pst_hdp->imgbytes;
st_hd.type = pst_hdp->type;
st_hd.plane = pst_hdp->plane;
/*
* Add tags for printing IFD
*/
/* New Subfile Type */
subfile |= 0x2; /* Subfile is single page of multi-page doc */
ADD_TAG(STNewSubfileType, ST_TAG_TYPE_LONG, 1, &subfile);
/* Resolution unit */
ADD_TAG(STResolutionUnit, ST_TAG_TYPE_SHORT, 1, &pst_hdp->resUnit);
/* X Resolution */
res[0] = (unsigned long)pst_hdp->xRes;
res[1] = 1;
ADD_TAG(STXResolution, ST_TAG_TYPE_RATIONAL, 1, res);
/* Y Resolution */
res[0] = (unsigned long)pst_hdp->yRes;
res[1] = 1;
ADD_TAG(STYResolution, ST_TAG_TYPE_RATIONAL, 1, res);
/* Thresholding */
ADD_TAG(STThresholding, ST_TAG_TYPE_SHORT, 1, &pst_hdp->thresholding);
/* Compression */
ADD_TAG(STCompression, ST_TAG_TYPE_SHORT, 1, &pst_hdp->compression);
/* Date and Time Stamp */
if (pst_hdp->dateTime && *(pst_hdp->dateTime)) {
ADD_TAG(STDateTime, ST_TAG_TYPE_ASCII, 20, pst_hdp->dateTime);
}
/* Host Computer */
if (pst_hdp->hostComputer && *(pst_hdp->hostComputer)) {
ADD_TAG(STHostComputer, ST_TAG_TYPE_ASCII,
strlen(pst_hdp->hostComputer) + 1, pst_hdp->hostComputer);
}
/* Software */
if (pst_hdp->software && *(pst_hdp->software)) {
ADD_TAG(STSoftware, ST_TAG_TYPE_ASCII,
strlen(pst_hdp->software) + 1, pst_hdp->software);
}
/* Document Name */
if (pst_hdp->docName && *(pst_hdp->docName)) {
ADD_TAG(STDocumentName, ST_TAG_TYPE_ASCII,
strlen(pst_hdp->docName) + 1, pst_hdp->docName);
}
/* Page Number */
ADD_TAG(STPageNumber, ST_TAG_TYPE_SHORT, 2, pst_hdp->pageNumbers);
/* Target Printer */
if (pst_hdp->targetPrinter && *(pst_hdp->targetPrinter)) {
ADD_TAG(STTargetPrinter, ST_TAG_TYPE_ASCII,
strlen(pst_hdp->targetPrinter) + 1, pst_hdp->targetPrinter);
}
/*
* Add SGI private data into the IFD. Currently we must call
* add_private_data with tags in ascending order.
*/
/* Ensure that we start clean so free the private data block */
free_private_data(&write_pblock);
/* Driver Options */
if (pst_hdp->driverOptions && *(pst_hdp->driverOptions)) {
ADD_PDATA(PSTPrivateDriverOptions, ST_TAG_TYPE_ASCII,
strlen(pst_hdp->driverOptions)+1, pst_hdp->driverOptions);
}
/* Put private data into the IFD */
if (create_private_tag(st, &write_pblock) < 0)
return -1;
/* Free the private data block */
free_private_data(&write_pblock);
/*
* Write the IFD
*/
status = STWriteImageHeader(st, &st_hd, last);
return status;
}
#undef ADD_TAG
/**************************************************************************
*
* Function: PSTReadImageHeader
*
* Description: Reads a Print STIFF image file header. This is a STIFF
* IFD with additional tags.
*
* Parameters:
* st (I) - STIFF stream pointer
* pst_hdp (I) - pointer to a Print STIFF header structure
*
* Return: 0 if successful and -1 if error.
*
**************************************************************************/
#define GET_TAG(tag) STGetTag(st, tag, &type, &len, &val)
#define GET_PDATA(id) get_private_data(&read_pblock, id, &type, &len, &val)
int PSTReadImageHeader(STStream *st, PSTImageHeader *pst_hdp)
{
STImageHeader st_hd;
STTagType type;
unsigned long len;
void *val;
static PRIVATE_DATA read_pblock;
/*
* Clear the header in case not all tags
* are found
*/
bzero((void*)pst_hdp, sizeof(PSTImageHeader));
/*
* Read the IFD
*/
if (STReadImageHeader(st, &st_hd) < 0)
return -1;
/*
* Fill in the structure with what we got back
*/
pst_hdp->width = st_hd.width;
pst_hdp->height = st_hd.height;
pst_hdp->bitsPerSample = st_hd.bitsPerSample;
pst_hdp->samplesPerPixel = st_hd.samplesPerPixel;
pst_hdp->imgbytes = st_hd.imgbytes;
pst_hdp->type = st_hd.type;
pst_hdp->plane = st_hd.plane;
/*
* Get printing specific tags, if any. If tag is
* not found don't stop, set field to default if
* available and move on to next tag. We don't want
* the read to fail if we are reading a base STIFF file
*/
/* Resolution unit */
pst_hdp->resUnit = (GET_TAG(STResolutionUnit) < 0) ?
PST_RES_UNIT_INCH: *((PSTResUnit*)val);
/* X Resolution */
if (GET_TAG(STXResolution) == 0)
pst_hdp->xRes = ((long*)val)[0] / ((long*)val)[1];
/* Y Resolution */
if (GET_TAG(STYResolution) == 0)
pst_hdp->yRes = ((long*)val)[0] / ((long*)val)[1];
/* Thresholding */
pst_hdp->thresholding = (GET_TAG(STThresholding) < 0) ?
PST_THRESHOLD_NONE: *((PSTThreshold*)val);
/* Compression */
pst_hdp->compression = (GET_TAG(STCompression) < 0) ?
PST_COMPRESSION_NONE: *((PSTCompression*)val);
/* Date and Time Stamp */
pst_hdp->dateTime = (GET_TAG(STDateTime) < 0) ? "": (char*)val;
/* Host Computer */
pst_hdp->hostComputer = (GET_TAG(STHostComputer) < 0) ? "": (char*)val;
/* Software */
pst_hdp->software = (GET_TAG(STSoftware) < 0) ? "": (char*)val;
/* Document Name */
pst_hdp->docName = (GET_TAG(STDocumentName) < 0) ? "": (char*)val;
/* Page Number */
if (GET_TAG(STPageNumber) == 0) {
pst_hdp->pageNumbers[0] = ((short*)val)[0];
pst_hdp->pageNumbers[1] = ((short*)val)[1];
}
/* Target Printer */
pst_hdp->targetPrinter = (GET_TAG(STTargetPrinter) < 0) ? "": (char*)val;
/*
* Read any SGI private data and set the PST structure
* fields accordingly
*/
/* Get the private tag */
if (GET_TAG(STSGIPrinting) == 0) {
read_pblock.items = (PSTPrivateData*)val;
read_pblock.amount = len;
} else {
read_pblock.items = NULL;
read_pblock.amount = 0;
}
/* Driver Options */
pst_hdp->driverOptions = (GET_PDATA(PSTPrivateDriverOptions) < 0) ?
"": (char*)val;
return 0;
}
#undef GET_TAG
/*
=========================================================================
LOCAL FUNCTIONS
=========================================================================
*/
/**************************************************************************
*
* Function: add_private_data
*
* Description: Adds the specified private data item into the private
* data item block. The block is maintained as an array and items are
* added to the end. All data is copied into the block, there are
* no pointers. This makes setting the private tag easier.
* IDs must be in ascending order so this functions must be called
* with private IDs in ascending order. Since we have little to add
* this is a reasonable assumption.
*
* Parameters:
* pblock (I) - private data block structure
* private_id (I) - ID of item to be added
* type (I) - type of data item
* len (I) - number of data items of type
* data (I) - data to be added
*
* Return: -1 if error, 0 if success.
*
**************************************************************************/
static int add_private_data(PRIVATE_DATA *pblock, unsigned short private_id,
STTagType type, unsigned long len, void *data)
{
register PSTPrivateData *pd, *ptr;
register unsigned long nItemBytes, nDataBytes;
/*
* Calculate the number of bytes for the data item.
* this is the size of the data structure plus the amount
* of data minus 4 for dummy data item.
*/
nDataBytes = len * _STTagTypeBytes(type);
nItemBytes = sizeof(PSTPrivateData) + nDataBytes - 4;
/*
* Create an entry in the data block
*/
if ((ptr = (PSTPrivateData*)((pblock->items == NULL) ? malloc(nItemBytes):
realloc(pblock->items, pblock->amount + nItemBytes))) == NULL) {
STerrno = STENOMEM;
return -1;
}
pblock->items = ptr;
/* LINTED */
pd = (PSTPrivateData*)((char*)pblock->items + pblock->amount);
/*
* Put the data in the block
*/
pd->private_id = private_id;
pd->type = type;
pd->len = len;
bcopy(data, pd->data, nDataBytes);
/*
* Update the amount of data running total
*/
pblock->amount += nItemBytes;
return 0;
}
/**************************************************************************
*
* Function: get_private_data
*
* Description: Searches the private data block for the specified private
* data item id. The block is assumed to be organized in ascending
* order of private IDs.
*
* Parameters:
* pblock (I) - private data block to search
* private_id (I) - private ID to search for
* typep (O) - type of data item
* lenp (O) - number of elements of type
* datap (O) - pointer to item data
*
* Return: 0 if item found. -1 if item not found.
*
**************************************************************************/
static int get_private_data(PRIVATE_DATA *pblock, unsigned short id,
STTagType *typep, unsigned long *lenp, void **datap)
{
register PSTPrivateData *ptr;
register unsigned long nbytes, offset = 0;
/*
* No sense checking if there is no data
*/
if (pblock->amount == 0) {
STerrno = STENOTFOUND;
return -1;
}
/*
* Search for the id
*/
while (offset < pblock->amount) {
/* LINTED */
ptr = (PSTPrivateData*)((char*)(pblock->items) + offset);
if (ptr->private_id == id) {
*typep = ptr->type;
*lenp = ptr->len;
*datap = ptr->data;
return 0;
}
if (ptr->private_id > id) {
STerrno = STENOTFOUND;
return -1;
}
nbytes = ptr->len * _STTagTypeBytes(ptr->type);
offset += sizeof(PSTPrivateData) + nbytes - 4;
}
STerrno = STENOTFOUND;
return -1;
}
/**************************************************************************
*
* Function: free_private_data
*
* Description: Deallocates storage for all private data.
*
* Parameters:
* pblock (I) - private data block structure
*
* Return: none
*
**************************************************************************/
static void free_private_data(PRIVATE_DATA *pblock)
{
/*
* Make sure we actually have data to free
*/
if (!pblock->amount)
return;
/*
* Free the private data
*/
free(pblock->items);
pblock->items = NULL;
pblock->amount = 0;
}
/**************************************************************************
*
* Function: create_private_tag
*
* Description: Creates the SGI private data tag entry in the IFD and
* then frees the private data block.
*
* Parameters:
* st (I) - STIFF stream
* pblock (I) - private data block structure
*
* Return: -1 if error, 0 if success
*
**************************************************************************/
static int create_private_tag(STStream *st, PRIVATE_DATA *pblock)
{
/*
* Make sure that there is a tag to create
*/
if (!pblock->amount) {
STerrno = STENOTFOUND;
return 0;
}
/*
* Add the tag to the IFD
*/
if (STAddTag(st, STSGIPrinting, ST_TAG_TYPE_UNDEFINED,
pblock->amount, (void*)(pblock->items)) < 0)
return -1;
return 0;
}